#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct stack {
    int depth;
    int used;
    int available;
    int msgSize;
    void *curPtr;
    void *bottomPtr;
} Stack_t;
typedef Stack_t *StackHandle_t;

StackHandle_t creatStack(int depth, int msgSize){
    StackHandle_t handle = malloc(sizeof(Stack_t));
    if(!handle){
        printf("malloc failed.\n");
        return NULL;
    }
    handle->bottomPtr = malloc(msgSize);
    if(!handle->bottomPtr){
        printf("malloc failed.\n");
        return NULL;
    }
    handle->curPtr = handle->bottomPtr;
    handle->depth = depth;
    handle->available = depth;
    handle->used = 0;
    handle->msgSize = msgSize;

    return handle;
}

int pushStack(StackHandle_t handle, void *msg){
    if(handle == NULL || msg == NULL){
        printf("handle or msg is null.");
        return 0;
    }
    if(handle->available > 0){
        handle->curPtr += handle->msgSize;
        memcpy(handle->curPtr, msg, handle->msgSize);
        handle->available--;
        handle->used++;                    
    }else{
        printf("stack is full.\n");
        return 0;
    }
    return handle->msgSize;    
}

int popStack(StackHandle_t handle, void *msg){
    if(handle == NULL || msg == NULL){
        printf("handle or msg is null.");
        return 0;
    }
    if(handle->used > 0){        
        memcpy(msg, handle->curPtr, handle->msgSize);
        handle->used--;
        handle->available++;     
        if(handle->used > 0)
            handle->curPtr -= handle->msgSize;  
    }else{
        printf("stack is empty.\n");
        return 0;
    }
    return handle->msgSize;
}

void releaseStack(StackHandle_t handle){
    free(handle->bottomPtr);
    free(handle);
}

int main(void){
    int msg = 1;
    int popmsg = 0;
    struct msgstrct
    {
        char name[10];
        int len;
        double data;
    } msgs, popmsgs;
    msgs.len = 100;
    msgs.data = 0.123;
    
    StackHandle_t stack1 = creatStack(6, sizeof(msg));
    int i;
    for(i = 0; i < 10; i++){
        if(pushStack(stack1, &msg)){
            printf("push: %d\n", msg);
            msg++;            
        }
    }
    for(i = 0; i < 10; i++){
        if(popStack(stack1, &popmsg)){
            printf("pop: %d\n", popmsg);
        }
    }
    releaseStack(stack1);

    StackHandle_t stack2 = creatStack(6, sizeof(msgs));
    for(i = 0; i < 10; i++){
        if(pushStack(stack2, &msgs)){
            printf("push: %d\n", msgs.len);
            msgs.len++;
        }
    }
    for(i = 0; i < 10; i++){
        if(popStack(stack2, &popmsgs)){
            printf("pop: %d\n", popmsgs.len);
        }
    }
    releaseStack(stack2);

    return 0;
}